#!/usr/bin/env python3  /*设定脚本文件直接能执行*/
# -*- coding:utf-8 -*-   /*设置编码*/
"""
@Author: zhuo
@Software: PyCharm
@File: tQControlForm.py
@Time: 2024/1/23 16:59
@Function：ctQControlForm：自定义电机控制界面类
"""
import os
from datetime import datetime
import pyqtgraph as pg
import pyqtgraph.exporters
from PySide6.QtCore import Qt
from PySide6.QtGui import QPixmap, QImage
from PySide6.QtWidgets import *
from tModels.tParaInfo import ctParaInfo
from tModels.tThread import ctShowThread
from tUI import tQTitleBar

RES_PATH = './ico/'                            # 资源文件基准地址
BLOWER_ICON = RES_PATH + "blower.png"          # 风机图标路径
TITLE_ICON = RES_PATH + "cosmo.png"            # 标题图标路径
START_ICON = RES_PATH + "start.png"            # 电机启动图标路径
STOP_ICNO = RES_PATH + "stop.png"              # 电机停止图标路径
POLL_ICON = RES_PATH + "poll.png"              # 参数轮询图标路径
STOPPOLL_ICON = RES_PATH + "stoppoll.png"      # 轮询停止图标路径
CLEAR_ICON = RES_PATH + "clear.png"            # 清除图标路径
CLEARHOVER_ICON = RES_PATH + "clearhover.png"  # 清除按键悬停图标路径
WARNING_ICON = RES_PATH + "warning.png"        # 警告图标路径
COSMO_BLUE = "#005AAA"                         # 卡奥斯蓝
HAIER_BLUE = "#1296DB"                         # 海尔蓝
ALARM_RED = "#FC5531"                          # 红色


class ctQControlForm(QHBoxLayout):
    """
    自定义电机控制界面类
    """

    # 初始化
    def __init__(self, widget, rtu, workbenchTab):
        # 继承自父类
        super(ctQControlForm, self).__init__()
        # 所在的widget
        self.controlTab = widget
        # 风机启动标识位
        self.isStart = False
        # 轮询启动标识位
        self.isPoll = False
        # 电机第一次启动标识位
        # V2.0.0要求每一次启动都输入转速
        # self.isFirstStart = False
        # Modbus通讯类
        self.rtu = rtu
        # 工作台界面类
        self.workbenchTab = workbenchTab
        # 参数类
        self.para = ctParaInfo()
        # 展示参数字典 add：地址 zoom：缩放倍数 value：最新获取的值
        self.showParaDic = {
            "相电流": {"add": "0000", "zoom": 10, "value": None},
            "母线电压": {"add": "0001", "zoom": 1, "value": None},
            "转速": {"add": "0002", "zoom": 1, "value": None},
            "温度": {"add": "0003", "zoom": 10, "value": None},
            "报警指示": {"add": "0004", "zoom": 1, "value": None}
        }
        # 展示参数报文发送解析线程
        self.showThread = ctShowThread(self.rtu, self.showParaDic)
        # 展示参数线程收到数据信号 连接槽函数
        self.showThread.connected.connect(self.__f_updateUI)

        # <editor-fold desc="绘图数据">
        # 曲线指针
        self.__m_curveCurrentPtr = 0
        self.__m_curveVoltagePtr = 0
        self.__m_curveRpmPtr = 0
        self.__m_curveTemPtr = 0

        # 曲线列表
        self.__m_currentCurveLst = []
        self.__m_voltageCurveLst = []
        self.__m_rpmCurveLst = []
        self.__m_temCurveLst = []
        self.__m_alarmCurveLst = []
        # X轴列表
        self.__m_currentXLst = []
        self.__m_voltageXLst = []
        self.__m_rpmXLst = []
        self.__m_temXLst = []

        # 获取数据的集合（温度、转速、母线电压、相电流、报警指示） 指针、数据列表、x轴当前时间、图形对象、曲线对象、显示数值按键
        self.showDataDic = {
            "相电流": {"ptr": self.__m_curveCurrentPtr, "list": self.__m_currentCurveLst, "x": self.__m_currentXLst,
                    "curve": None, "plot": None, "btn": None},
            "母线电压": {"ptr": self.__m_curveVoltagePtr, "list": self.__m_voltageCurveLst, "x": self.__m_voltageXLst,
                     "curve": None, "plot": None, "btn": None},
            "转速": {"ptr": self.__m_curveRpmPtr, "list": self.__m_rpmCurveLst, "x": self.__m_rpmXLst, "curve": None,
                   "plot": None, "btn": None},
            "温度": {"ptr": self.__m_curveTemPtr, "list": self.__m_temCurveLst, "x": self.__m_temXLst, "curve": None,
                   "plot": None, "btn": None},
            "报警指示": {"ptr": None, "list": self.__m_alarmCurveLst, "x": None, "btn": None}
        }
        # </editor-fold>
        # 方向 正转：1；反转：0
        self.direction = None

        # 调用控制界面布局函数
        self.__f_controlLayout()

    # 控制界面布局函数
    def __f_controlLayout(self):
        """
        function:  控制界面布局函数
              in:  None
             out:  None
          return:  None
          others:  Control Form Layout Func
        """
        # 总体布局:：垂直布局
        self.mainLayout = QHBoxLayout()

        # <editor-fold desc="创建布局">
        # 设置总布局
        self.controlTab.setLayout(self.mainLayout)
        # 左侧布局垂直布局
        leftLayout = QHBoxLayout()
        # 中间布局：垂直布局
        middleLayout = QVBoxLayout()
        # 右侧布局：垂直布局
        rightLayout = QHBoxLayout()
        # </editor-fold>

        # <editor-fold desc="左边布局控件">
        # 垂直Spacer
        spacerV = QSpacerItem(80, 150, QSizePolicy.Minimum, QSizePolicy.Expanding)
        leftLblLayout = QVBoxLayout()
        lbl1 = QLabel("电机正反转")
        lbl1.setFixedSize(80, 25)
        lbl2 = QLabel("电机启停控制")
        lbl2.setFixedSize(80, 25)
        lbl3 = QLabel("电机参数轮询")
        lbl3.setFixedSize(80, 25)
        lbl4 = QLabel("报警信息清除")
        lbl4.setFixedSize(80, 25)
        lbl5 = QLabel("电机转速设置")
        lbl5.setFixedSize(80, 25)
        leftLblLayout.addWidget(lbl1)
        leftLblLayout.addWidget(lbl2)
        leftLblLayout.addWidget(lbl3)
        leftLblLayout.addWidget(lbl4)
        leftLblLayout.addWidget(lbl5)
        leftLblLayout.addItem(spacerV)
        leftLayout.addLayout(leftLblLayout)
        leftBtnLayout = QVBoxLayout()
        # 创建电机正反转选择框
        self.cbbDirection = QComboBox()
        self.cbbDirection.addItems(["正转", "反转"])
        # 设置为固定尺寸
        self.cbbDirection.setFixedSize(80, 25)
        self.btnControl = QPushButton()
        self.btnControl.setObjectName("btnControl")
        # 设置为固定尺寸
        self.btnControl.setFixedSize(25, 25)
        # 设置电机控制按键的图片
        self.btnControl.setStyleSheet("#btnControl{border-image:url(%s);}" % START_ICON)
        self.btnControl.clicked.connect(self.__f_startAndStopFunc)
        self.btnPoll = QPushButton()
        self.btnPoll.setObjectName("btnPoll")
        self.btnPoll.setFixedSize(25, 25)
        self.btnPoll.setStyleSheet("#btnPoll{border-image:url(%s);}" % POLL_ICON)
        self.btnPoll.clicked.connect(self.__f_pollAndStopFunc)
        self.btnClear = QPushButton()
        self.btnClear.setFixedSize(25, 25)
        self.btnClear.setObjectName("btnClear")
        self.btnClear.clicked.connect(self.__f_alarmClearFunc)
        self.btnClear.setStyleSheet("#btnClear{border-image:url(%s);}"
                                    "#btnClear:pressed{border-image:url(%s)}" % (CLEAR_ICON, CLEARHOVER_ICON))
        speedLayout = QHBoxLayout()

        # 创建转速写入文本框
        self.txtSpeed = QLineEdit()
        self.txtSpeed.setFixedSize(40, 25)
        self.txtSpeed.setEnabled(False)
        self.btnSpeed = QPushButton("写入")
        self.btnSpeed.setFixedSize(40, 25)
        self.btnSpeed.clicked.connect(self.__f_speedWriteFunc)
        self.btnSpeed.setEnabled(False)
        speedLayout.addWidget(self.txtSpeed)
        speedLayout.addWidget(self.btnSpeed)
        leftBtnLayout.addWidget(self.cbbDirection)
        leftBtnLayout.addWidget(self.btnControl)
        leftBtnLayout.addWidget(self.btnPoll)
        leftBtnLayout.addWidget(self.btnClear)
        leftBtnLayout.addLayout(speedLayout)
        leftBtnLayout.addItem(spacerV)
        leftLayout.addLayout(leftBtnLayout)
        # </editor-fold>

        # <editor-fold desc="中间布局控件">

        # <editor-fold desc="GraphicsLayoutWidget">
        self.pw = pg.GraphicsLayoutWidget(show=True)
        # 修改背景色
        self.pw.setBackground(tQTitleBar.COLOR_DARK)
        # 创建坐标的标签
        self.pwLabel = pg.LabelItem(justify='right')
        # 将坐标添加到GraphicsLayoutWidget布局中来
        self.pw.addItem(self.pwLabel)
        # 调用创建曲线对象函数
        self.current = self.__f_SetGraph(0, 0, "相电流", "A")
        self.voltage = self.__f_SetGraph(0, 1, "母线电压", "V")
        self.rpm = self.__f_SetGraph(1, 0, "转速", "rpm")
        self.tem = self.__f_SetGraph(1, 1, "温度", "℃")
        # Plot对象
        self.currentPlot = self.current[0]
        self.voltagePlot = self.voltage[0]
        self.rpmPlot = self.rpm[0]
        self.temPlot = self.tem[0]
        self.showDataDic["相电流"]["plot"] = self.currentPlot
        self.showDataDic["母线电压"]["plot"] = self.voltagePlot
        self.showDataDic["转速"]["plot"] = self.rpmPlot
        self.showDataDic["温度"]["plot"] = self.temPlot
        # 坐标轴X
        self.currentX = self.current[1]
        self.voltageX = self.voltage[1]
        self.rpmX = self.rpm[1]
        self.temX = self.tem[1]
        self.showDataDic["相电流"]["xax"] = self.currentX
        self.showDataDic["母线电压"]["xax"] = self.voltageX
        self.showDataDic["转速"]["xax"] = self.rpmX
        self.showDataDic["温度"]["xax"] = self.temX
        # 曲线列表
        self.__m_temCurveLst = [0] * 1
        self.__m_rpmCurveLst = [0] * 1
        self.__m_voltageCurveLst = [0] * 1
        self.__m_currentCurveLst = [0] * 1
        self.currentCurve = self.currentPlot.plot(self.__m_currentCurveLst, pen=pg.mkPen(f'{HAIER_BLUE}', width=4),
                                                  name="相电流曲线")
        self.voltageCurve = self.voltagePlot.plot(self.__m_voltageCurveLst, pen=pg.mkPen(f'{HAIER_BLUE}', width=4),
                                                  name="母线电压曲线")
        self.rpmCurve = self.rpmPlot.plot(self.__m_rpmCurveLst, pen=pg.mkPen(f'{HAIER_BLUE}', width=4), name="转速曲线")
        self.temCurve = self.temPlot.plot(self.__m_temCurveLst, pen=pg.mkPen(f'{HAIER_BLUE}', width=4),
                                          name="温度曲线")
        # Curve对象
        self.showDataDic["相电流"]["curve"] = self.currentCurve
        self.showDataDic["母线电压"]["curve"] = self.voltageCurve
        self.showDataDic["转速"]["curve"] = self.rpmCurve
        self.showDataDic["温度"]["curve"] = self.temCurve

        # <editor-fold desc="创建曲线上的点和跟随线">
        # 创建曲线上的点
        self.rpmPoint = pg.CurvePoint(self.rpmCurve)
        # 鼠标跟随的垂直方向的线
        self.rpmVLine = pg.InfiniteLine(angle=90, movable=False)
        # 鼠标跟随的水平方向的线
        self.rpmHLine = pg.InfiniteLine(angle=0, movable=False)
        self.rpmPlot.addItem(self.rpmVLine, ignoreBounds=True)
        self.rpmPlot.addItem(self.rpmHLine, ignoreBounds=True)
        # 不含有坐标轴，但有鼠标功能的支持，获取鼠标事件,用户可以使用鼠标缩放/平移 ViewBox 的内容
        self.rpmVb = self.rpmPlot.vb

        self.temPoint = pg.CurvePoint(self.temCurve)
        self.temVLine = pg.InfiniteLine(angle=90, movable=False)
        self.temHLine = pg.InfiniteLine(angle=0, movable=False)
        self.temPlot.addItem(self.temVLine, ignoreBounds=True)
        self.temPlot.addItem(self.temHLine, ignoreBounds=True)
        self.temVb = self.temPlot.vb

        self.currentPoint = pg.CurvePoint(self.currentCurve)
        self.currentVLine = pg.InfiniteLine(angle=90, movable=False)
        self.currentHLine = pg.InfiniteLine(angle=0, movable=False)
        self.currentPlot.addItem(self.currentVLine, ignoreBounds=True)
        self.currentPlot.addItem(self.currentHLine, ignoreBounds=True)
        self.currentVb = self.currentPlot.vb

        self.voltagePoint = pg.CurvePoint(self.voltageCurve)
        self.voltageVLine = pg.InfiniteLine(angle=90, movable=False)
        self.voltageHLine = pg.InfiniteLine(angle=0, movable=False)
        self.voltagePlot.addItem(self.voltageVLine, ignoreBounds=True)
        self.voltagePlot.addItem(self.voltageHLine, ignoreBounds=True)
        self.voltageVb = self.voltagePlot.vb

        self.rpmProxy = pg.SignalProxy(self.rpmPlot.scene().sigMouseMoved, rateLimit=60, slot=self.__f_mouseMoved)
        self.temProxy = pg.SignalProxy(self.temPlot.scene().sigMouseMoved, rateLimit=60, slot=self.__f_mouseMoved)
        self.currentProxy = pg.SignalProxy(self.currentPlot.scene().sigMouseMoved, rateLimit=60,
                                           slot=self.__f_mouseMoved)
        self.voltageProxy = pg.SignalProxy(self.voltagePlot.scene().sigMouseMoved, rateLimit=60,
                                           slot=self.__f_mouseMoved)
        # </editor-fold>

        middleLayout.addWidget(self.pw)
        # </editor-fold>

        # <editor-fold desc="曲线下方布局">
        # 初始化 窗口模式选择框
        self.ckbWindowMode = QCheckBox("窗口模式")
        self.ckbWindowMode.stateChanged.connect(self.__f_handleWindowModeChanged)
        # 初始化 自动缩放选择框
        self.ckbAutoMode = QCheckBox("缩放模式")
        self.ckbAutoMode.stateChanged.connect(self.__f_handleAutoModeChanged)
        # 初始化 保存图像按钮
        self.btnSavePic = QPushButton("保存图像")
        self.btnSavePic.clicked.connect(self.__f_btnSaveImageClicked)
        # 初始化 清空图像按键
        self.btnClearPic = QPushButton("清空图像")
        self.btnClearPic.clicked.connect(self.__f_btnClearPicClicked)
        self.alarmLayout = QHBoxLayout()
        # 水平Spacer
        self.spacerAlarm = QSpacerItem(600, 15, QSizePolicy.Expanding, QSizePolicy.Minimum)
        self.alarmLayout.addItem(self.spacerAlarm)
        self.alarmLayout.addWidget(self.btnClearPic)
        self.alarmLayout.addWidget(self.btnSavePic)
        self.alarmLayout.addWidget(self.ckbAutoMode)
        self.alarmLayout.addWidget(self.ckbWindowMode)
        # </editor-fold>

        middleLayout.addLayout(self.alarmLayout)
        # </editor-fold>

        # <editor-fold desc="右边布局控件">
        lblCurrent = QLabel("相    电   流：")
        lblCurrent.setFixedSize(80, 25)
        lblVoltage = QLabel("母 线 电 压：")
        lblVoltage.setFixedSize(80, 25)
        lblRpm = QLabel("转          速：")
        lblRpm.setFixedSize(80, 25)
        lblTem = QLabel("温          度：")
        lblTem.setFixedSize(80, 25)
        lblAlarm = QLabel("报 警 提 示：")
        lblAlarm.setFixedSize(80, 25)
        # 垂直Spacer
        spacerLbl = QSpacerItem(15, 150, QSizePolicy.Minimum, QSizePolicy.Expanding)
        rightLblLayout = QVBoxLayout()
        btnCurrent = QPushButton()
        btnCurrent.setEnabled(False)
        btnCurrent.setFixedSize(80, 25)
        btnCurrent.setStyleSheet(f" color:{HAIER_BLUE};font-size: 10pt;font-weight:bold;")
        self.showDataDic["相电流"]["btn"] = btnCurrent
        btnVoltage = QPushButton()
        btnVoltage.setEnabled(False)
        btnVoltage.setFixedSize(80, 25)
        btnVoltage.setStyleSheet(f" color:{HAIER_BLUE};font-size: 10pt;font-weight:bold;")
        self.showDataDic["母线电压"]["btn"] = btnVoltage
        btnRpm = QPushButton()
        btnRpm.setEnabled(False)
        btnRpm.setFixedSize(80, 25)
        btnRpm.setStyleSheet(f" color:{HAIER_BLUE};font-size: 10pt;font-weight:bold;")
        self.showDataDic["转速"]["btn"] = btnRpm
        btnTem = QPushButton()
        btnTem.setEnabled(False)
        btnTem.setFixedSize(80, 25)
        btnTem.setStyleSheet(f" color:{HAIER_BLUE};font-size: 10pt;font-weight:bold;")
        self.showDataDic["温度"]["btn"] = btnTem
        btnAlarm = QPushButton()
        btnAlarm.setEnabled(False)
        btnAlarm.setFixedSize(80, 25)
        self.showDataDic["报警指示"]["btn"] = btnAlarm
        rightBtnLayout = QVBoxLayout()
        rightBtnLayout.addWidget(btnCurrent)
        rightBtnLayout.addWidget(btnVoltage)
        rightBtnLayout.addWidget(btnRpm)
        rightBtnLayout.addWidget(btnTem)
        rightBtnLayout.addWidget(btnAlarm)
        rightBtnLayout.addItem(spacerLbl)
        rightLblLayout.addWidget(lblCurrent)
        rightLblLayout.addWidget(lblVoltage)
        rightLblLayout.addWidget(lblRpm)
        rightLblLayout.addWidget(lblTem)
        rightLblLayout.addWidget(lblAlarm)
        rightLblLayout.addItem(spacerLbl)

        rightUnitLayout = QVBoxLayout()
        lbl6 = QLabel("A")
        lbl6.setFixedSize(25, 25)
        lbl7 = QLabel("V")
        lbl7.setFixedSize(25, 25)
        lbl8 = QLabel("rpm")
        lbl8.setFixedSize(25, 25)
        lbl9 = QLabel("℃")
        lbl9.setFixedSize(25, 25)
        lbl10 = QLabel("")
        lbl10.setFixedSize(25, 25)
        rightUnitLayout.addWidget(lbl6)
        rightUnitLayout.addWidget(lbl7)
        rightUnitLayout.addWidget(lbl8)
        rightUnitLayout.addWidget(lbl9)
        rightUnitLayout.addWidget(lbl10)
        rightUnitLayout.addItem(spacerLbl)
        rightLayout.addLayout(rightLblLayout)
        rightLayout.addLayout(rightBtnLayout)
        rightLayout.addLayout(rightUnitLayout)
        # </editor-fold>

        self.mainLayout.addLayout(leftLayout)
        self.mainLayout.addLayout(middleLayout)
        self.mainLayout.addLayout(rightLayout)

    # <editor-fold desc="按键响应函数">
    # 电机启动停止函数
    def __f_startAndStopFunc(self):
        """
        function:  电机启动停止函数
              in:  None
             out:  None
          return:  None
          others:  Motor Start & Stop Func
        """
        # 判断串口是否打开
        if self.rtu.f_readComIsOpen() == 2:
            # 判断是否在轮询
            if self.isPoll:
                QMessageBox.information(self.controlTab, '提示', '轮询尚未停止！', QMessageBox.Yes)
            # 如果未在轮询
            else:
                # 已启动
                if self.isStart:
                    ir = self.rtu.f_modbusExecute(1, 6,
                                                  self.para.motorStartControlPraDic["启动/停止"]["add"], 0)
                    # 发送电机停止指令收发正确，说明电机已经停止
                    if ir["resMode"] == 1:
                        # 停止
                        self.isStart = False
                        self.txtSpeed.setEnabled(False)
                        self.btnSpeed.setEnabled(False)
                        self.btnControl.setStyleSheet("#btnControl{border-image:url(%s);}" % START_ICON)
                        self.workbenchTab.stateBox.dicMsg["运行状态"]["txt"].setText(
                            str("电机已停止"))
                        self.workbenchTab.stateBox.dicMsg["运行状态"]["txt"].setStyleSheet(
                            f" color:{HAIER_BLUE};font-size: 10pt;font-weight:bold;")
                        self.workbenchTab.blower.f_stop()
                        new_time = datetime.now().strftime('[%Y-%m-%d %H-%M-%S]')
                        self.workbenchTab.txtSysLog.appendPlainText(f"{new_time}  :  电机已停止")
                    return self.isStart
                # 已停止
                else:
                    # # 判断是否是第一次启动
                    # if not self.isFirstStart:
                    # 转速输入提示框
                    speed, okPressed = QInputDialog.getText(self.btnControl, "提示", "请输入启动转速", QLineEdit.Normal, "")
                    # 如果点击取消
                    if not okPressed:
                        pass
                    # 点击确定
                    else:
                        # 判断输入的字符串是否为数字
                        if speed.isdigit():
                            # 发送设置转速报文
                            ir = self.rtu.f_modbusExecute(1, 6, self.para.motorStartControlPraDic["转速"]["add"],
                                                          speed)
                            # 判断转速是否设置成功
                            if ir["resMode"] == 1:
                                if self.cbbDirection.currentText() == "正转":
                                    self.direction = 1
                                    ir = self.rtu.f_modbusExecute(1, 6,
                                                                  self.para.motorStartControlPraDic["正反转"]["add"],
                                                                  self.direction)
                                else:
                                    self.direction = 0
                                    ir = self.rtu.f_modbusExecute(1, 6,
                                                                  self.para.motorStartControlPraDic["正反转"]["add"],
                                                                  self.direction)
                                # 判断电机正反转是否设置成功
                                if ir["resMode"] == 1:
                                    ir = self.rtu.f_modbusExecute(1, 6,
                                                                  self.para.motorStartControlPraDic["启动/停止"]["add"],
                                                                  1)
                                # 判断电机是否启动成功
                                if ir["resMode"] == 1:
                                    # 启动标识位设置
                                    self.isStart = True
                                    self.txtSpeed.setEnabled(True)
                                    self.btnSpeed.setEnabled(True)
                                    self.btnControl.setStyleSheet("#btnControl{border-image:url(%s);}" % STOP_ICNO)
                                    self.isFirstStart = True
                                    self.workbenchTab.stateBox.dicMsg["运行状态"]["txt"].setText(
                                        str("电机运行中"))
                                    self.workbenchTab.stateBox.dicMsg["运行状态"]["txt"].setStyleSheet(
                                        f" color:{HAIER_BLUE};font-size: 10pt;font-weight:bold;")
                                    new_time = datetime.now().strftime('[%Y-%m-%d %H-%M-%S]')
                                    self.workbenchTab.txtSysLog.appendPlainText(f"{new_time}  :  电机已启动")
                                return self.isStart
                # 不是第一次启动
                # else:
                #     if self.cbbDirection.currentText() == "正转":
                #         self.direction = 1
                #         ir = self.rtu.f_modbusExecute(1, 6,
                #                                       self.para.motorStartControlPraDic["正反转"]["add"],
                #                                       self.direction)
                #     else:
                #         self.direction = 0
                #         ir = self.rtu.f_modbusExecute(1, 6,
                #                                       self.para.motorStartControlPraDic["正反转"]["add"],
                #                                       self.direction)
                #     # 判断电机正反转是否设置成功
                #     if ir["resMode"] == 1:
                #         ir = self.rtu.f_modbusExecute(1, 6,
                #                                       self.para.motorStartControlPraDic["启动/停止"]["add"], 1)
                #     # 判断电机是否启动成功
                #     if ir["resMode"] == 1:
                #         # 启动
                #         self.isStart = True
                #         self.txtSpeed.setEnabled(True)
                #         self.btnSpeed.setEnabled(True)
                #         self.btnControl.setStyleSheet("#btnControl{border-image:url(%s);}" % STOP_ICNO)
                #         self.workbenchTab.stateBox.dicMsg["运行状态"]["txt"].setText(
                #             str("电机运行中"))
                #         self.workbenchTab.stateBox.dicMsg["运行状态"]["txt"].setStyleSheet(
                #             f" color:{HAIER_BLUE};font-size: 10pt;font-weight:bold;")
                #         new_time = datetime.now().strftime('[%Y-%m-%d %H-%M-%S]')
                #         self.workbenchTab.txtSysLog.appendPlainText(f"{new_time}  :  电机已启动")
                #     return self.isStart

    # 轮询启动停止函数
    def __f_pollAndStopFunc(self):
        """
        function:  轮询启动停止函数
              in:  None
             out:  None
          return:  None
          others:  Polling Start And Stop Func
        """
        # 判断串口是否打开
        if self.rtu.f_readComIsOpen() == 2:
            # 已启动
            if self.isPoll:
                # V2.0.0 要增加自动停止轮询的功能：调用轮询停止函数
                self.isPoll = self.f_pollStopFunc()
            # 已停止
            else:
                # 调用轮询启动函数
                self.isPoll = self.f_pollStartFunc()

    # 转速写入按键响应函数
    def __f_speedWriteFunc(self):
        """
        function:  转速写入按键响应函数
              in:  None
             out:  None
          return:  None
          others:  Speed Written Button Response Func
        """
        # 判断串口是否打开
        if self.rtu.f_readComIsOpen() == 2:
            # 判断是否在轮询
            if self.isPoll:
                QMessageBox.information(self.controlTab, '提示', '轮询尚未停止！', QMessageBox.Yes)
            else:
                # 判断电机是否启动
                if self.isStart:
                    # 获取输入的转速
                    speed = self.txtSpeed.text()
                    # 判断输入的字符串是否为数字
                    if speed.isdigit():
                        # 发送设置转速报文
                        ir = self.rtu.f_modbusExecute(1, 6, self.para.motorStartControlPraDic["转速"]["add"],
                                                      speed)
                        # 判断设置转速是否成功
                        if ir["resMode"] == 1:
                            # 获取当前时间
                            new_time = datetime.now().strftime('[%Y-%m-%d %H-%M-%S]')
                            # 工作台系统日志添加信息
                            self.workbenchTab.txtSysLog.appendPlainText(f"{new_time}  :  电机转速设置为 {speed} rpm")

    # 报警清除响应函数
    def __f_alarmClearFunc(self):
        """
        function:  报警清除响应函数
              in:  None
             out:  None
          return:  None
          others:  Alarm Clear Response Func
        """
        # 判断串口是否打开
        if self.rtu.f_readComIsOpen() == 2:
            # 判断是否在轮询
            if self.isPoll:
                QMessageBox.information(self.controlTab, '提示', '轮询尚未停止！', QMessageBox.Yes)
            else:
                # 发送清除报警报文
                ir = self.rtu.f_modbusExecute(1, 6, self.para.motorStartControlPraDic["清除报警"]["add"],
                                              1)
                # 判断清除报警信息是否成功
                if ir["resMode"] == 1:
                    # 获取当前时间
                    new_time = datetime.now().strftime('[%Y-%m-%d %H-%M-%S]')
                    # 工作台系统日志添加信息
                    self.workbenchTab.txtSysLog.appendPlainText(f"{new_time}  :  电机报警已清除")

    # 保存图像按钮按下处理函数
    def __f_btnSaveImageClicked(self):
        """
        function:  保存图像按钮按下处理函数
              in:  None
             out:  None
          return:  ir=True ok, ir=False some wrong
          others:  handle function of the button Save Image clicked
        """
        # 获取当前文件所在文件夹路径
        folder_path = os.getcwd()
        # 测试结果图片存放路径
        save_path_dir = f"{folder_path}\\Result"
        # 判断该路径是否存在
        if not os.path.exists(save_path_dir):
            # 如果不存在则创建
            os.makedirs(save_path_dir)
        # 获取当前时间
        now_time = datetime.now()
        # 设置时间输出格式
        new_time = now_time.strftime('[%Y-%m-%d %H-%M-%S]')
        # 创建pyqtgraph.exporters对象
        ex = pg.exporters.ImageExporter(self.pw.scene())
        # 创建图片文件路径
        file_path = f"{save_path_dir}\\{new_time}电机运行曲线.png"
        # 调用pyqtgraph.exporters的export方法
        ex.export(file_path)
        if os.path.exists(file_path):
            QMessageBox.information(self.controlTab, '提示', '图像保存成功!', QMessageBox.Yes)
            # 获取当前时间
            new_time = datetime.now().strftime('[%Y-%m-%d %H-%M-%S]')
            # 工作台系统日志添加信息
            self.workbenchTab.txtSysLog.appendPlainText(f"{new_time}  :  电机运行曲线.png 保存成功")

    # 清空图像按键响应函数
    def __f_btnClearPicClicked(self):
        """
        function:  清空图像按键响应函数
              in:  None
             out:  None
          return:  None
          others:  Clear Image Button Response Func
        """
        # 清空曲线列表
        self.__m_temCurveLst.clear()
        self.__m_rpmCurveLst.clear()
        self.__m_currentCurveLst.clear()
        self.__m_voltageCurveLst.clear()
        # 清空X轴时间列表
        self.__m_temXLst.clear()
        self.__m_rpmXLst.clear()
        self.__m_currentXLst.clear()
        self.__m_voltageXLst.clear()
        # 曲线指针置零
        self.__m_curveRpmPtr = 0
        self.__m_curveTemPtr = 0
        self.__m_curveCurrentPtr = 0
        self.__m_curveVoltagePtr = 0
        # 展示数据集合赋值 指针、列表、X轴时间
        self.showDataDic["相电流"]["ptr"] = self.__m_curveCurrentPtr
        self.showDataDic["相电流"]["list"] = self.__m_currentCurveLst
        self.showDataDic["相电流"]["x"] = self.__m_currentXLst
        # 母线电压
        self.showDataDic["母线电压"]["ptr"] = self.__m_curveVoltagePtr
        self.showDataDic["母线电压"]["list"] = self.__m_voltageCurveLst
        self.showDataDic["母线电压"]["x"] = self.__m_voltageXLst
        # 转速
        self.showDataDic["转速"]["ptr"] = self.__m_curveRpmPtr
        self.showDataDic["转速"]["list"] = self.__m_rpmCurveLst
        self.showDataDic["转速"]["x"] = self.__m_rpmXLst
        # 温度
        self.showDataDic["温度"]["ptr"] = self.__m_curveTemPtr
        self.showDataDic["温度"]["list"] = self.__m_temCurveLst
        self.showDataDic["温度"]["x"] = self.__m_temXLst
        # 曲线动态赋值
        self.__f_plotDataAdd(self.__m_curveTemPtr, self.__m_temCurveLst, self.temPlot, self.temCurve,
                             self.__m_temXLst, self.temX)
        self.__f_plotDataAdd(self.__m_curveRpmPtr, self.__m_rpmCurveLst, self.rpmPlot, self.rpmCurve,
                             self.__m_rpmXLst, self.rpmX)
        self.__f_plotDataAdd(self.__m_curveCurrentPtr, self.__m_currentCurveLst, self.currentPlot,
                             self.currentCurve, self.__m_currentXLst, self.currentX)
        self.__f_plotDataAdd(self.__m_curveVoltagePtr, self.__m_voltageCurveLst, self.voltagePlot,
                             self.voltageCurve, self.__m_voltageXLst, self.voltageX)
        # 展示参数实时展示的按键文本清空
        self.showDataDic["相电流"]["btn"].setText("")
        self.showDataDic["母线电压"]["btn"].setText("")
        self.showDataDic["转速"]["btn"].setText("")
        self.showDataDic["温度"]["btn"].setText("")
        self.showDataDic["报警指示"]["btn"].setText("")
        # 转速、温度、相电流、母线电压曲线设置X、Y轴范围
        self.rpmPlot.setXRange(0, 10)
        self.rpmPlot.setYRange(0, 10)
        self.temPlot.setXRange(0, 10)
        self.temPlot.setYRange(0, 10)
        self.currentPlot.setXRange(0, 10)
        self.currentPlot.setYRange(0, 10)
        self.voltagePlot.setXRange(0, 10)
        self.voltagePlot.setYRange(0, 10)

    # </editor-fold>

    # <editor-fold desc="选择框变化函数">
    # 窗口模式选择框变化处理函数
    def __f_handleWindowModeChanged(self):
        """
        function:  窗口模式选择框变化处理函数
              in:  None
             out:  None
          return:  None
          others:  Window Mode Selection Box Change Handler
        """
        # 判断是否是窗口模式
        if self.ckbWindowMode.isChecked():
            # 判断曲线指针是否大于8
            if self.showDataDic["温度"]["ptr"] > 8:
                # 当大于8时，只显示最后8个点
                self.temPlot.setXRange(self.showDataDic["温度"]["ptr"] - 8, self.showDataDic["温度"]["ptr"])
            if self.showDataDic["转速"]["ptr"] > 8:
                self.rpmPlot.setXRange(self.showDataDic["转速"]["ptr"] - 8, self.showDataDic["转速"]["ptr"])
            if self.showDataDic["相电流"]["ptr"] > 8:
                self.currentPlot.setXRange(self.showDataDic["相电流"]["ptr"] - 8, self.showDataDic["相电流"]["ptr"])
            if self.showDataDic["母线电压"]["ptr"] > 8:
                self.voltagePlot.setXRange(self.showDataDic["母线电压"]["ptr"] - 8, self.showDataDic["母线电压"]["ptr"])
        # 不是窗口模式，则显示全部信息
        else:
            self.showDataDic["温度"]["plot"].setXRange(0, self.showDataDic["温度"]["ptr"])
            self.showDataDic["转速"]["plot"].setXRange(0, self.showDataDic["转速"]["ptr"])
            self.showDataDic["相电流"]["plot"].setXRange(0, self.showDataDic["相电流"]["ptr"])
            self.showDataDic["母线电压"]["plot"].setXRange(0, self.showDataDic["母线电压"]["ptr"])

    # 自动缩放选择框变化处理函数
    def __f_handleAutoModeChanged(self):
        """
        function:  缩放模式选择框变化处理函数
              in:  None
             out:  None
          return:  None
          others:  Zoom Mode Select Box Change Handler Func
        """
        # 判断是否选择了自动缩放模式
        if self.ckbAutoMode.isChecked():
            self.pwLabel.setText("")
            # 显示PlotItem对象 的 自动缩放按钮“A”(左下角)
            self.rpmPlot.showButtons()
            # 启用轴操作
            self.rpmPlot.setMouseEnabled(x=True, y=False)
            # 显示PlotItem对象 的 自动缩放按钮“A”(左下角)
            self.temPlot.showButtons()
            # 启用轴操作
            self.temPlot.setMouseEnabled(x=True, y=False)
            # 显示PlotItem对象 的 自动缩放按钮“A”(左下角)
            self.currentPlot.showButtons()
            # 启用轴操作
            self.currentPlot.setMouseEnabled(x=True, y=False)
            # 显示PlotItem对象 的 自动缩放按钮“A”(左下角)
            self.voltagePlot.showButtons()
            # 启用轴操作
            self.voltagePlot.setMouseEnabled(x=True, y=False)
        else:
            # 隐藏PlotItem对象 的 自动缩放按钮“A”(左下角)
            self.rpmPlot.hideButtons()
            # 禁用轴操作
            self.rpmPlot.setMouseEnabled(x=False, y=False)
            # 隐藏PlotItem对象 的 自动缩放按钮“A”(左下角)
            self.temPlot.hideButtons()
            # 禁用轴操作
            self.temPlot.setMouseEnabled(x=False, y=False)
            # 隐藏PlotItem对象 的 自动缩放按钮“A”(左下角)
            self.currentPlot.hideButtons()
            # 禁用轴操作
            self.currentPlot.setMouseEnabled(x=False, y=False)
            # 隐藏PlotItem对象 的 自动缩放按钮“A”(左下角)
            self.voltagePlot.hideButtons()
            # 禁用轴操作
            self.voltagePlot.setMouseEnabled(x=False, y=False)

    # </editor-fold>

    # <editor-fold desc="接收信号更新UI函数">
    # 展示线程接收到数据后更新UI
    def __f_updateUI(self, name, dic):
        """
        function:  展示线程接收到数据后更新UI
              in:  name：
                   dic：
             out:  None
          return:  None
          others:  The Show Thread Update The UI After Received The Data
        """
        for k, v in self.showDataDic.items():
            if name == k:
                if k != "报警指示":
                    # 获取当前时间，设置为x轴显示时间的模式
                    new_time = datetime.now().strftime('%H:%M:%S')
                    # 获取当前时间，设置为工作台系统日志添加信息的时间模式
                    new_time2 = datetime.now().strftime('[%Y-%m-%d %H-%M-%S]')
                    value = dic["value"]
                    # 数值去0并转换为字符串类型
                    no_zero_value = str(self.__f_removeExtraZero(value))
                    # 获取参数的单位信息
                    unit = self.para.showPraDic[k]["unit"]
                    # 指针+1
                    self.showDataDic[k]["ptr"] += 1
                    self.showDataDic[k]["list"].append(value)
                    self.showDataDic[k]["x"].append(new_time)
                    self.__f_plotDataAdd(self.showDataDic[k]["ptr"], self.showDataDic[k]["list"],
                                         self.showDataDic[k]["plot"],
                                         self.showDataDic[k]["curve"], self.showDataDic[k]["x"],
                                         self.showDataDic[k]["xax"])
                    self.showDataDic[k]["btn"].setText(no_zero_value)
                    self.workbenchTab.stateBox.dicMsg[k]["txt"].setText(no_zero_value)
                    self.workbenchTab.stateBox.dicMsg[k]["txt"].setStyleSheet(
                        f" color:{HAIER_BLUE};font-size: 10pt;font-weight:bold;")
                    if k == "转速":
                        if self.direction == 1:
                            # 设置控制台的风机转速
                            self.workbenchTab.blower.f_setSpeed(dic["value"])
                        else:
                            # 设置控制台的风机转速
                            self.workbenchTab.blower.f_setSpeed(-dic["value"])
                    self.workbenchTab.txtSysLog.appendPlainText(f"{new_time2}  :  电机{k} --> {no_zero_value} {unit}")
                else:
                    self.__f_alarmFunc(dic["value"], self.showDataDic[k]["btn"])

    # </editor-fold>

    # <editor-fold desc="用到的私有方法">
    # pyqtgraph增加图例函数
    def __f_SetGraph(self, row, col, label, unit):
        """
        function:  pyqtgraph增加图例函数
              in:  row:行数
                   col:列数
                   label:标签名称
                   unit:单位
             out:  curve:曲线对象
                   xax:坐标轴X
          return:  curve,xax
          others:  Pyqtgraph add legend function
        """
        # PlotItem图形对象
        curve = self.pw.addPlot(row=row, col=col)
        # 显示表格线
        curve.showGrid(x=True, y=True)
        # 下采样模式
        curve.setDownsampling(mode='peak')
        # 字体颜色和大小
        labelStyle = {'color': f'{HAIER_BLUE}', 'font-size': '12pt', "units": unit}
        # 设置上下左右的label
        curve.setLabel("bottom", label, **labelStyle)
        # 1、自定义plotItem坐标轴：获取plotItem的'bottom'轴对象
        # 坐标轴x 获取plotItem的'bottom'轴
        xax = curve.getAxis("bottom")
        # 是否可见
        curve.setClipToView(True)
        # 隐藏PlotItem对象 的 自动缩放按钮“A”(左下角)
        curve.hideButtons()
        # 禁用轴操作
        curve.setMouseEnabled(x=False, y=False)
        # 曲线对象设置X轴范围
        curve.setXRange(0, 10)
        # 曲线对象设置Y轴范围
        curve.setYRange(0, 10)
        # 返回曲线对象和坐标轴X
        return curve, xax

    # GraphicsLayoutWidget 鼠标移动响应函数
    def __f_mouseMoved(self, evt):
        """
        function:  鼠标移动响应函数
              in:  None
             out:  None
          return:  None
          others:  Mouse movement response function
        """
        if not self.ckbAutoMode.isChecked():
            try:
                # 使用信号代理将原始参数转换为元组，获取事件的鼠标位置
                pos = evt[0]
                # 鼠标所处的X轴坐标
                rpm_mouse_point = self.rpmVb.mapSceneToView(pos)
                # 鼠标所处的X轴坐标
                tem_mouse_point = self.temVb.mapSceneToView(pos)
                # 鼠标所处的X轴坐标
                current_mouse_point = self.currentVb.mapSceneToView(pos)
                # 鼠标所处的X轴坐标
                voltage_mouse_point = self.voltageVb.mapSceneToView(pos)
                # 判断是否是窗口模式.
                if self.ckbWindowMode.isChecked() and \
                        self.showDataDic["转速"]["ptr"] > 8 and \
                        self.showDataDic["温度"]["ptr"] > 8 and \
                        self.showDataDic["相电流"]["ptr"] > 8 and \
                        self.showDataDic["母线电压"]["ptr"] > 8:
                    # 如果鼠标位置在绘图部件中
                    if self.rpmPlot.sceneBoundingRect().contains(pos) or \
                            self.temPlot.sceneBoundingRect().contains(pos) or \
                            self.currentPlot.sceneBoundingRect().contains(pos) or \
                            self.voltagePlot.sceneBoundingRect().contains(pos):

                        rpmStart = self.showDataDic["转速"]["ptr"] - 18
                        modeRpmX = rpm_mouse_point.x() - rpmStart - 9

                        currentStart = self.showDataDic["相电流"]["ptr"] - 18
                        modeCurrentX = current_mouse_point.x() - currentStart - 9

                        temStart = self.showDataDic["温度"]["ptr"] - 9
                        modeTemX = tem_mouse_point.x() - temStart

                        voltageStart = self.showDataDic["母线电压"]["ptr"] - 9
                        modeVoltageX = voltage_mouse_point.x() - voltageStart
                        # 判断plot是否有大于一个点
                        if self.showDataDic["转速"]["ptr"] > 1 and \
                                self.showDataDic["母线电压"]["ptr"] > 1 and \
                                self.showDataDic["温度"]["ptr"] > 1 and \
                                self.showDataDic["相电流"]["ptr"] > 1:
                            # Point设置位置的float类型范围是0-1
                            self.rpmPoint.setPos(modeRpmX / 8)
                            # Point设置位置的float类型范围是0-1
                            self.temPoint.setPos(modeTemX / 8)
                            # Point设置位置的float类型范围是0-1
                            self.currentPoint.setPos(modeCurrentX / 8)
                            # Point设置位置的float类型范围是0-1
                            self.voltagePoint.setPos(modeVoltageX / 8)

                            self.pwLabel.setText(
                                f"<span style='color: {HAIER_BLUE}'>相电流:%0.1fA  </span>\n"
                                f"<span style='color: {HAIER_BLUE}'>母线电压:%0.1fV  </span>\n"
                                f"<span style='color: {HAIER_BLUE}'>转速:%0.1frpm  </span>\n"
                                f"<span style='color: {HAIER_BLUE}'>温度:%0.1f℃</span>\n"
                                % (
                                    self.currentPoint.pos().y(),
                                    self.voltagePoint.pos().y(),
                                    self.rpmPoint.pos().y(),
                                    self.temPoint.pos().y(),
                                ))
                            # 设置垂直线的位置
                            self.rpmVLine.setPos(rpm_mouse_point.x())
                            # 设置水平线的位置
                            self.rpmHLine.setPos(rpm_mouse_point.y())
                            # 设置垂直线的位置
                            self.temVLine.setPos(tem_mouse_point.x())
                            # 设置水平线的位置
                            self.temHLine.setPos(tem_mouse_point.y())
                            # 设置垂直线的位置
                            self.currentVLine.setPos(current_mouse_point.x())
                            # 设置水平线的位置
                            self.currentHLine.setPos(current_mouse_point.y())
                            # 设置垂直线的位置
                            self.voltageVLine.setPos(voltage_mouse_point.x())
                            # 设置水平线的位置
                            self.voltageHLine.setPos(voltage_mouse_point.y())
                else:
                    # 如果鼠标位置在绘图部件中
                    if self.rpmPlot.sceneBoundingRect().contains(pos) or self.temPlot.sceneBoundingRect().contains(
                            pos) or self.currentPlot.sceneBoundingRect().contains(
                        pos) or self.voltagePlot.sceneBoundingRect().contains(pos):
                        # 判断plot是否有大于一个点
                        if self.showDataDic["转速"]["ptr"] > 1 and \
                                self.showDataDic["母线电压"]["ptr"] > 1 and \
                                self.showDataDic["温度"]["ptr"] > 1 and \
                                self.showDataDic["相电流"]["ptr"] > 1:
                            # Point设置位置的float类型范围是0-1
                            self.rpmPoint.setPos(
                                rpm_mouse_point.x() / (self.showDataDic["转速"]["ptr"] - 1))
                            # Point设置位置的float类型范围是0-1
                            self.temPoint.setPos(
                                tem_mouse_point.x() / (self.showDataDic["温度"]["ptr"] - 1))
                            # Point设置位置的float类型范围是0-1
                            self.currentPoint.setPos(
                                current_mouse_point.x() / (
                                        self.showDataDic["相电流"]["ptr"] - 1))
                            # Point设置位置的float类型范围是0-1
                            self.voltagePoint.setPos(
                                voltage_mouse_point.x() / (
                                        self.showDataDic["母线电压"]["ptr"] - 1))
                            self.pwLabel.setText(
                                f"<span style='color: {HAIER_BLUE}'>相电流:%0.1fA  </span>\n"
                                f"<span style='color: {HAIER_BLUE}'>母线电压:%0.1fV  </span>\n"
                                f"<span style='color: {HAIER_BLUE}'>转速:%0.1frpm  </span>\n"
                                f"<span style='color: {HAIER_BLUE}'>温度:%0.1f℃</span>\n"
                                % (
                                    self.currentPoint.pos().y(),
                                    self.voltagePoint.pos().y(),
                                    self.rpmPoint.pos().y(),
                                    self.temPoint.pos().y(),
                                ))
                            # 设置垂直线的位置
                            self.rpmVLine.setPos(rpm_mouse_point.x())
                            # 设置水平线的位置
                            self.rpmHLine.setPos(rpm_mouse_point.y())
                            # 设置垂直线的位置
                            self.temVLine.setPos(tem_mouse_point.x())
                            # 设置水平线的位置
                            self.temHLine.setPos(tem_mouse_point.y())
                            # 设置垂直线的位置
                            self.currentVLine.setPos(current_mouse_point.x())
                            # 设置水平线的位置
                            self.currentHLine.setPos(current_mouse_point.y())
                            # 设置垂直线的位置
                            self.voltageVLine.setPos(voltage_mouse_point.x())
                            # 设置水平线的位置
                            self.voltageHLine.setPos(voltage_mouse_point.y())
            except Exception as e:
                print(e)

    # 曲线数据动态增加
    def __f_plotDataAdd(self, ptr, lst, plot, curve, xLst, xax):
        """
        function:  曲线数据动态增加：初始的列表为10个，然后10个10个的增加列表的值 ，再赋给曲线
              in:  ptr：曲线指针
                   lst：曲线数据列表
                   plot：画图对象
                   curve：曲线对象
                   xLst:刻度值列表，即时间
                   xax：plotItem的'bottom'对象
             out:
          return:  int >0 ok, <0 some wrong
          others:  Curve data increase dynamically
        """
        # 3、自定义plotItem坐标轴：刻度值与显示数值绑定
        ticks = [list(zip(range(ptr), xLst))]  # [[(0, '13:52:44'), (1, '13:52:47')]]  # 刻度值与曲线数值绑定
        # 初始的列表为10个，然后10个10个的增加列表的值 ，再赋给曲线
        # 如果指针大小 > 温度数据点列表
        if ptr >= len(lst):
            # 获取当前的列表
            pLst = lst
            # 列表长度+1
            lst = [0 for i in range(len(lst) + 1)]
            # 将之前获取的列表值 赋值给新列表
            lst[:len(pLst)] = pLst
        # 判断是否是窗口模式.
        if self.ckbWindowMode.isChecked():
            # 判断曲线指针是否大于8
            if ptr > 8:
                # 重新绘制图形
                curve.setData(lst[:ptr])
                # 4、自定义plotItem坐标轴：设置bottom轴的刻度数值显示
                # 设置bottom轴的刻度数值显示
                xax.setTicks(ticks)
                # 设置y轴范围，y轴的最大值加上50
                plot.setYRange(0, max(lst) + 50)
                # 当大于8时，只显示最后8个点
                plot.setXRange(ptr - 8, ptr)
            else:
                # 重新绘制图形
                curve.setData(lst[:ptr])
                # 设置bottom轴的刻度数值显示
                xax.setTicks(ticks)
                # 设置y轴
                plot.setYRange(0, max(lst) + 50)
                # 设置x轴
                plot.setXRange(0, ptr)
        else:
            # 设置x轴
            plot.setXRange(0, ptr)
            # 重新绘制图形
            curve.setData(lst[:ptr])
            # 设置bottom轴的刻度数值显示
            xax.setTicks(ticks)
            # 设置y轴
            plot.setYRange(0, max(lst) + 50)

    # 报警判断函数
    def __f_alarmFunc(self, alarm, btn):
        """
        function:  报警判断函数
              in:  alarm:报警指示的十进制数值
                   btn:报警指示的按键
             out:  None
          return:  None
          others:  Alarm judgment function
        """
        # E001:57345 硬件过流报警
        # E002:57346 软件过流报警
        # E003:57347 电压过压报警
        # E004:57348 电压欠压报警
        # E005:57349 电机缺项报警
        # E006:57350 电机堵转报警
        # E007:57351 功率过温报警
        # E008:57352 预留
        # E009:573453 偏置电压报警
        new_time = datetime.now().strftime('[%H-%M-%S]')
        if alarm == 57345:
            btn.setText("硬件过流报警")
            btn.setStyleSheet(f" color:{ALARM_RED};font-size: 10pt;font-weight:bold;")
            self.__f_alarmTextInsertIcon(f"硬件过流报警     {new_time}")
            self.workbenchTab.alarmBox.alarmTimes += 1
            self.workbenchTab.alarmBox.lblTimes.setText(str(self.workbenchTab.alarmBox.alarmTimes))
        elif alarm == 57346:
            btn.setText("软件过流报警")
            btn.setStyleSheet(f" color:{ALARM_RED};font-size: 10pt;font-weight:bold;")
            self.__f_alarmTextInsertIcon(f"软件过流报警     {new_time}")
            self.workbenchTab.alarmBox.alarmTimes += 1
            self.workbenchTab.alarmBox.lblTimes.setText(str(self.workbenchTab.alarmBox.alarmTimes))
        elif alarm == 57347:
            btn.setText("电压过压报警")
            btn.setStyleSheet(f" color:{ALARM_RED};font-size: 10pt;font-weight:bold;")
            self.__f_alarmTextInsertIcon(f"电压过压报警     {new_time}")
            self.workbenchTab.alarmBox.alarmTimes += 1
            self.workbenchTab.alarmBox.lblTimes.setText(str(self.workbenchTab.alarmBox.alarmTimes))
        elif alarm == 57348:
            btn.setText("电压欠压报警")
            btn.setStyleSheet(f" color:{ALARM_RED};font-size: 10pt;font-weight:bold;")
            self.__f_alarmTextInsertIcon(f"电压欠压报警     {new_time}")
            self.workbenchTab.alarmBox.alarmTimes += 1
            self.workbenchTab.alarmBox.lblTimes.setText(str(self.workbenchTab.alarmBox.alarmTimes))
        elif alarm == 57349:
            btn.setText("电机缺项报警")
            btn.setStyleSheet(f" color:{ALARM_RED};font-size: 10pt;font-weight:bold;")
            self.__f_alarmTextInsertIcon(f"电机缺项报警     {new_time}")
            self.workbenchTab.alarmBox.alarmTimes += 1
            self.workbenchTab.alarmBox.lblTimes.setText(str(self.workbenchTab.alarmBox.alarmTimes))
        elif alarm == 57350:
            btn.setText("电机堵转报警")
            btn.setStyleSheet(f" color:{ALARM_RED};font-size: 10pt;font-weight:bold;")
            self.__f_alarmTextInsertIcon(f"电机堵转报警     {new_time}")
            self.workbenchTab.alarmBox.alarmTimes += 1
            self.workbenchTab.alarmBox.lblTimes.setText(str(self.workbenchTab.alarmBox.alarmTimes))
        elif alarm == 57351:
            btn.setText("功率过温报警")
            btn.setStyleSheet(f" color:{ALARM_RED};font-size: 10pt;font-weight:bold;")
            self.__f_alarmTextInsertIcon(f"功率过温报警     {new_time}")
            self.workbenchTab.alarmBox.alarmTimes += 1
            self.workbenchTab.alarmBox.lblTimes.setText(str(self.workbenchTab.alarmBox.alarmTimes))
        elif alarm == 57352:
            btn.setText("偏置电压报警")
            btn.setStyleSheet(f" color:{ALARM_RED};font-size: 10pt;font-weight:bold;")
            self.__f_alarmTextInsertIcon(f"偏置电压报警     {new_time}")
            self.workbenchTab.alarmBox.alarmTimes += 1
            self.workbenchTab.alarmBox.lblTimes.setText(str(self.workbenchTab.alarmBox.alarmTimes))
        else:
            btn.setText("无报警")
            btn.setStyleSheet(f" color:{HAIER_BLUE};font-size: 10pt;font-weight:bold;")

    # 报警信息文本框插入图片
    def __f_alarmTextInsertIcon(self, txt):
        """
        function:  报警信息文本框插入图片
              in:  txt：写入的内容
             out:  None
          return:  None
          others:  Alarm Message Text Box Insert Pic
        """
        # 加载图片
        pixmap = QImage(WARNING_ICON)
        # 调整图片大小和比例
        pixmap = pixmap.scaled(32, 32, Qt.IgnoreAspectRatio, Qt.SmoothTransformation)
        # 获取光标
        cursor = self.workbenchTab.alarmBox.txtAlarmMsg.textCursor()
        # 在文档中插入图片
        cursor.insertImage(pixmap)
        self.workbenchTab.alarmBox.txtAlarmMsg.insertPlainText(f"   {txt}")
        self.workbenchTab.alarmBox.txtAlarmMsg.insertPlainText("\n")
        # 设置文本对齐方式为居中
        self.workbenchTab.alarmBox.txtAlarmMsg.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)

    # </editor-fold>

    # <editor-fold desc="静态方法">
    # 去掉小数点后多余的0
    @staticmethod
    def __f_removeExtraZero(n):
        """
        function:  去掉小数点后多余的0
              in:  n:去除前的数
             out:  n:去除后的数
          return:  n:int
          others:  Remove Extra 0 After The Decimal Point
        """
        # 先去除多余的0
        n = n - 0
        # 转变为字符串类型
        n = str(n)
        # 判断n是否以’.0‘结尾
        if n.endswith('.0'):
            # 是则删除’.0‘  即用空白符取代
            n = n.replace('.0', '')
            # 转变回int类型
            n = int(n)
        return n

    # </editor-fold>

    # 轮询启动函数
    def f_pollStartFunc(self):
        """
        function:  轮询启动函数
              in:  None
             out:  True
          return:  bool
          others:  Poll Start Func
        """
        # 启动
        self.btnPoll.setStyleSheet("#btnPoll{border-image:url(%s);}" % STOPPOLL_ICON)
        # 将清空图像按键设置为禁用
        self.btnClearPic.setEnabled(False)
        # 线程开启
        self.showThread.start()
        # 线程运行标志位置为True
        self.showThread.isRunning = True
        # 获取当前时间
        new_time = datetime.now().strftime('[%Y-%m-%d %H-%M-%S]')
        self.workbenchTab.txtSysLog.appendPlainText(f"{new_time}  :  轮询开始")
        print("轮询已开始")
        return True

    # 轮询停止函数
    def f_pollStopFunc(self):
        """
        function:  轮询停止函数
              in:  None
             out:  False
          return:  bool
          others:  Poll Stop Func
        """
        # 停止
        self.btnPoll.setStyleSheet("#btnPoll{border-image:url(%s);}" % POLL_ICON)
        # 停止控制台的风机转动
        self.workbenchTab.blower.f_stop()
        # 线程停止
        self.showThread.stop()
        # 线程运行标志位置为False
        self.showThread.isRunning = False
        # 获取当前时间
        new_time = datetime.now().strftime('[%Y-%m-%d %H-%M-%S]')
        # 工作日志 添加文本
        self.workbenchTab.txtSysLog.appendPlainText(f"{new_time}  :  轮询停止")
        # 将清空图像按键设置为启用
        self.btnClearPic.setEnabled(True)
        print("轮询已停止")
        return False
